package com.leboncoin.xml;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import com.leboncoin.bean.SearchItemBean;
import com.leboncoin.bean.SubscriptionBean;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;

public class ConfigManager {

    static final Logger logger = Logger.getLogger(ConfigManager.class.getName());
    Document configuration;
    List<SubscriptionBean> subscriptions = null;
    String senderEmail;
    String senderPassword;
    Map<String, String> urlParameterMapping;

    static final String[] price = {"0", "25000", "50000", "75000", "100000", "125000", "150000", 
        "175000", "200000", "225000", "250000", "275000", "300000", "325000", "350000", "400000", 
        "450000", "500000", "550000", "600000", "650000", "700000", "800000", "900000", "1000000", 
        "1100000", "1200000", "1300000", "1400000", "1500000", "2000000"};

    static ConfigManager singleton;

    public final static Map<String, String> CATEGORIES = new HashMap<>();
    static {
        CATEGORIES.put("Ventes immobilières", "ventes_immobilieres");
        CATEGORIES.put("Locations", "locations");
        CATEGORIES.put("Voitures", "voitures");
    }
    
    
    public enum TAG_NAMES {

        NAME("name"), EMAIL_ADRESS("emailAdress"), EMAIL_PASSWORD("emailPassword"), 
        SEARCH_ITEM("searchItem"), SEARCH_CATEGORY("searchCategory", ""),
        SEARCH_TEXT("searchText", "q"), PRICE_MIN("priceMin", "ps"), PRICE_MAX("priceMax", "pe"), 
        CHECK_OPTION("checkoption"), LOCATION("location", "location");

        String tagName;
        String urlParameter;

        TAG_NAMES(String tagName, String urlParameter) {
            this.tagName = tagName;
            this.urlParameter = urlParameter;
        }

        TAG_NAMES(String tagName) {
            this.tagName = tagName;
        }

        public String getUrlParameter() {
            return urlParameter;
        }

        @Override
        public String toString() {
            return tagName;
        }
    }

    public static ConfigManager getInstance(String fileName) {
        if (singleton == null) {
            if (fileName == null) {
                throw new java.lang.IllegalArgumentException(ConfigManager.class.getSimpleName() + " : config file name mandatory for the first singleton access");
            }
            singleton = new ConfigManager(fileName);
        }
        return singleton;
    }

    private ConfigManager(String fileName) {
        super();

        try {
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            this.configuration = dBuilder.parse(new File(fileName));
            configuration.getDocumentElement().normalize();
            subscriptions = new ArrayList<SubscriptionBean>();
            parseXmlConfig();

        } catch (IOException e) {
            logger.log(Level.SEVERE, "Cannot open config file:{0}", fileName);
            throw new IllegalArgumentException(e);
        } catch (SAXException e) {
            logger.log(Level.SEVERE, "Cannot parse config file:" + fileName, e);
            throw new IllegalArgumentException(e);
        } catch (ParserConfigurationException e) {
            logger.log(Level.SEVERE, "Cannot parse config file:" + fileName, e);
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Parse recherche.xml config file
     */
    protected final void parseXmlConfig() {
        Element root = configuration.getDocumentElement();
        logger.log(Level.INFO, "Root element :{0}", root.getNodeName());
        this.senderEmail = root.getElementsByTagName(TAG_NAMES.EMAIL_ADRESS.toString()).item(0).getTextContent();
        this.senderPassword = root.getElementsByTagName(TAG_NAMES.EMAIL_PASSWORD.toString()).item(0).getTextContent();
        NodeList subscriptionNodes = root.getElementsByTagName("subscription");
        for (int i = 0; i < subscriptionNodes.getLength(); i++) {

            Element subscription = (Element) subscriptionNodes.item(i);
            SubscriptionBean subscriptionBean = new SubscriptionBean();

            subscriptionBean.setName(subscription.getElementsByTagName(TAG_NAMES.NAME.toString()).item(0).getTextContent());

            NodeList adressList = subscription.getElementsByTagName(TAG_NAMES.EMAIL_ADRESS.toString());
            for (int j = 0; j < adressList.getLength(); j++) {
                subscriptionBean.getEmailAdresses().add(adressList.item(j).getTextContent());
            }
            
            NodeList itemNodeList = subscription.getElementsByTagName(TAG_NAMES.SEARCH_ITEM.toString());
            for (int j = 0; j < itemNodeList.getLength(); j++) {

                Element itemElement = (Element) itemNodeList.item(j);

                SearchItemBean searchItemBean = new SearchItemBean();
                subscriptionBean.getSearchItems().add(searchItemBean);

                if (itemElement.getElementsByTagName(TAG_NAMES.SEARCH_CATEGORY.toString()).getLength() > 0) {
                    searchItemBean.setSearchCategory(itemElement.getElementsByTagName(TAG_NAMES.SEARCH_CATEGORY.toString()).item(0).getTextContent());
                }
                searchItemBean.setSearchText(itemElement.getElementsByTagName(TAG_NAMES.SEARCH_TEXT.toString()).item(0).getTextContent());

                NodeList priceMinList = itemElement.getElementsByTagName(TAG_NAMES.PRICE_MIN.toString());
                if (priceMinList.getLength() > 0 && priceMinList.item(0).getTextContent() != null && !priceMinList.item(0).getTextContent().isEmpty()) {
                    searchItemBean.setPriceMin(Integer.parseInt(priceMinList.item(0).getTextContent()));
                }
                NodeList priceMaxList = itemElement.getElementsByTagName(TAG_NAMES.PRICE_MAX.toString());
                if (priceMaxList.getLength() > 0 && priceMaxList.item(0).getTextContent() != null && !priceMaxList.item(0).getTextContent().isEmpty()) {
                    searchItemBean.setPriceMax(Integer.parseInt(priceMaxList.item(0).getTextContent()));
                    logger.info("xxxxxxxxx"+searchItemBean.getPriceMax());
                }

                NodeList checkOptionList = itemElement.getElementsByTagName(TAG_NAMES.CHECK_OPTION.toString());
                if (checkOptionList.getLength() > 0) {
                    for (int k = 0; k < checkOptionList.getLength(); k++) {
                        Element checkOptionElement = (Element) checkOptionList.item(k);
                        searchItemBean.getCheckBoxList().add(checkOptionElement.getAttribute("id"));
                    }
                }

                NodeList locationList = itemElement.getElementsByTagName(TAG_NAMES.LOCATION.toString());
                if (locationList.getLength() > 0) {
                    Element locationElement = (Element) locationList.item(0);
                    String locationType = locationElement.getAttribute("type");
                    if (locationType.equals(SearchItemBean.LocationType.FRANCE.name())) {
                        searchItemBean.setSearchLocation(SearchItemBean.LocationType.FRANCE);
                    } else if (locationType.equals(SearchItemBean.LocationType.AUVERGNE.name())) {
                        searchItemBean.setSearchLocation(SearchItemBean.LocationType.AUVERGNE);
                    } else if (locationType.equals(SearchItemBean.LocationType.PUY_DE_DOME.name())) {
                        searchItemBean.setSearchLocation(SearchItemBean.LocationType.PUY_DE_DOME);
                    } else if (locationType.equals(SearchItemBean.LocationType.DEP_VOISINS.name())) {
                        searchItemBean.setSearchLocation(SearchItemBean.LocationType.DEP_VOISINS);
                    } 
                    NodeList zipCodeList = locationElement.getElementsByTagName("zipCode");
                    if (zipCodeList != null) {
                        for (int k = 0; k < zipCodeList.getLength(); k++){
                            Element zipCodeElement = (Element) zipCodeList.item(k);
                            searchItemBean.getZipCodes().add(zipCodeElement.getTextContent());
                        }
                    }

                }
            }
            subscriptions.add(subscriptionBean);
        }
    }

    public Document getConfiguration() {
        return configuration;
    }

    public void setConfiguration(Document configuration) {
        this.configuration = configuration;
    }

    public List<SubscriptionBean> getSubscriptions() {
        return subscriptions;
    }

    public void setSubscriptions(List<SubscriptionBean> subscriptions) {
        this.subscriptions = subscriptions;
    }

    public Map<String, String> getUrlParameterMapping() {
        return urlParameterMapping;
    }

    public void setUrlParameterMapping(Map<String, String> urlParameterMapping) {
        this.urlParameterMapping = urlParameterMapping;
    }

    /** Return search index of the given price (search index = leboncoin rank) */
    public Integer getPrice(String priceString) {
        Integer result = null;
        for (int i = 0; i < price.length; i++) {
            if (price[i].equals(priceString)) {
                result = i;
                break;
            }
        }
        return result;
    }

    public String getSenderPassword() {
        return senderPassword;
    }
    
    public String getSenderEmail() {
        return senderEmail;
    }
}
